package com.deliveryservicesystem.presentation.desktop.addpanel;

import com.deliveryservicesystem.app.exceptions.OutputError;
import com.deliveryservicesystem.app.exceptions.PreexistingEntityException;
import com.deliveryservicesystem.app.factory.AppFactory;
import com.deliveryservicesystem.app.util.AppUtils;
import com.deliveryservicesystem.app.validation.DeliveryValidator;
import com.deliveryservicesystem.app.validation.ValidationUtil;
import com.deliveryservicesystem.dataaccess.PersistenceDbManager;
import com.deliveryservicesystem.model.Delivery;
import com.deliveryservicesystem.model.Driver;
import com.deliveryservicesystem.presentation.desktop.InfoLableChangeHandler;
import com.deliveryservicesystem.presentation.desktop.MatchDialog;
import com.deliveryservicesystem.service.crud.impl.DeliveryCrudServiceImpl;
import com.jgoodies.binding.PresentationModel;
import com.jgoodies.validation.ValidationResult;
import com.jgoodies.validation.view.ValidationComponentUtils;
import com.jgoodies.validation.view.ValidationResultViewFactory;
import com.toedter.calendar.JDateChooser;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
import javax.swing.JOptionPane;

/**
 * File Name: AddEditDeliveryPanel.java
 * Version:
 * Description:
 * Package: com.deliveryservicesystem.presentation.desktop.addpanel
 * Author: Lance
 * Date: Jun 27, 2012
 * Editor:
 */
public class AddEditDeliveryDialog extends javax.swing.JDialog
{

    private static final long serialVersionUID = 1L;
    private PresentationModel presentationModel;
    private DeliveryCrudServiceImpl deliveryCrudService;
    private Delivery deliveryFromDb;
    private JDateChooser dateChooser;
    private PersistenceDbManager dbManager;

    public AddEditDeliveryDialog(java.awt.Frame parent, boolean modal, HashMap<String, String> values)
    {
        super(parent, modal);
        dbManager = PersistenceDbManager.getInstance();
        dateChooser = new JDateChooser(null, new Date(), null, new com.toedter.calendar.JSpinnerDateEditor());
        dateChooser.getJCalendar().setTodayButtonVisible(true);
        initComponents();
        cbDriverNo.setSelectedIndex(-1);
        deliveryCrudService = new DeliveryCrudServiceImpl();
        if (!values.isEmpty())
        {
            lblDeliveryNo.setText(values.get("DELIVERY NUMBER"));
            ckbDelivered.setSelected((values.get("IS DELIVERED").equals("Yes")) ? true : false); //ans = (a < b) ? a : b
            cbDriverNo.setSelectedItem(new Driver(Integer.parseInt(values.get("DRIVER NUMBER"))));
            try
            {
                String dateFormatConverter = AppUtils.dateFormatConverter(values.get("DELIVERY DATE"), "dd MMM yyyy", "yyyy-MM-dd", Locale.ENGLISH);
                dateChooser.setDate(java.sql.Date.valueOf(dateFormatConverter));
            }
            catch (ParseException ex)
            {
                OutputError.toLog(ex);
                OutputError.toUser(ex);
            }
            deliveryFromDb = deliveryCrudService.findById(Integer.parseInt(values.get("DELIVERY NUMBER")));
        }

        ValidationComponentUtils.setInputHint(dateChooser, "Please enter the delivery date");
        ValidationComponentUtils.setInputHint(ckbDelivered, "Check if the delivery is delivered");
        ValidationComponentUtils.setInputHint(cbDriverNo, "Select a diver number for the delivery");

        presentationModel = new PresentationModel(new DeliveryValidator(dateChooser, ckbDelivered.isSelected(), cbDriverNo.getSelectedItem()));
        //Bindings.bind(ckbDelivered, presentationModel.getBufferedModel("ckbDelivered"));

        KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(new InfoLableChangeHandler(lblInfo));
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        entityManager = dbManager.getEntityManager();
        driverQuery = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery("SELECT d FROM Driver d");
        driverList = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : driverQuery.getResultList();
        jLabel1 = new javax.swing.JLabel();
        lblDeliveryDate = new javax.swing.JLabel();
        lblDeliveryNo = new javax.swing.JLabel();
        jSeparator2 = new javax.swing.JSeparator();
        lblValidationErrors = new javax.swing.JLabel();
        lblValidationErrors.setVisible(false);
        lblDelivered = new javax.swing.JLabel();
        lblInfo = new javax.swing.JLabel();
        btnMatch = new javax.swing.JButton();
        btnCancel = new javax.swing.JButton();
        txtDate = new javax.swing.JTextField();
        btnOk = new javax.swing.JButton();
        lblDriverNo = new javax.swing.JLabel();
        ckbDelivered = new javax.swing.JCheckBox();
        cbDriverNo = new javax.swing.JComboBox();
        jSeparator1 = new javax.swing.JSeparator();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jLabel1.setText("Derlivery Number");

        lblDeliveryDate.setText("Delivery Date");

        lblDeliveryNo.setText("New Number is Generated");

        lblValidationErrors.setIcon(ValidationResultViewFactory.getCheckIcon());
        lblValidationErrors.setText("Validation Errors");

        lblDelivered.setText("Delivered");

        lblInfo.setIcon(ValidationResultViewFactory.getInfoIcon());
        lblInfo.setText("Info Label");

        btnMatch.setText("Match");
        btnMatch.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnMatchActionPerformed(evt);
            }
        });

        btnCancel.setText("Cancel");
        btnCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCancelActionPerformed(evt);
            }
        });

        txtDate.setText("Date");

        btnOk.setText("OK");
        btnOk.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnOkActionPerformed(evt);
            }
        });

        lblDriverNo.setText("Driver Number");

        ckbDelivered.setText("Is delivered");

        cbDriverNo.setRenderer(new DefaultListCellRenderer()
            {

                @Override
                public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
                {
                    super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                    if (value instanceof Driver)
                    {
                        Driver driver = (Driver) value;
                        setText(driver.getDriverNo().toString());
                    }
                    return this;
                }
            });

            org.jdesktop.swingbinding.JComboBoxBinding jComboBoxBinding = org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, driverList, cbDriverNo, "driver");
            bindingGroup.addBinding(jComboBoxBinding);
            org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, driverList, org.jdesktop.beansbinding.ObjectProperty.create(), cbDriverNo, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "driverno");
            bindingGroup.addBinding(binding);

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
                .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                            .addGap(0, 0, Short.MAX_VALUE)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                    .addComponent(btnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                    .addComponent(btnCancel))
                                .addComponent(lblInfo, javax.swing.GroupLayout.Alignment.TRAILING)))
                        .addGroup(layout.createSequentialGroup()
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createSequentialGroup()
                                    .addComponent(jLabel1)
                                    .addGap(18, 18, 18)
                                    .addComponent(lblDeliveryNo))
                                .addComponent(lblDelivered)
                                .addGroup(layout.createSequentialGroup()
                                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(lblDriverNo)
                                        .addComponent(lblDeliveryDate))
                                    .addGap(18, 18, 18)
                                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(ckbDelivered)
                                        .addGroup(layout.createSequentialGroup()
                                            .addComponent(cbDriverNo, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                            .addComponent(btnMatch))
                                        .addComponent(dateChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                .addComponent(lblValidationErrors))
                            .addGap(0, 51, Short.MAX_VALUE)))
                    .addContainerGap())
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jLabel1)
                        .addComponent(lblDeliveryNo))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 11, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(layout.createSequentialGroup()
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(lblDeliveryDate)
                                .addComponent(dateChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(lblDelivered)
                                .addComponent(ckbDelivered))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(lblDriverNo)
                                .addComponent(cbDriverNo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(btnMatch))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addComponent(lblValidationErrors)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 134, Short.MAX_VALUE))
                        .addGroup(layout.createSequentialGroup()
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(btnOk)
                                .addComponent(btnCancel))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))
                    .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(lblInfo)
                    .addGap(17, 17, 17))
            );

            bindingGroup.bind();

            pack();
        }// </editor-fold>//GEN-END:initComponents

    private void btnMatchActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnMatchActionPerformed
    {//GEN-HEADEREND:event_btnMatchActionPerformed
        try
        {
            MatchDialog frame = new MatchDialog(null, true, "BEGIN ? := GET_DATA.DRIVERS; END;");
            AppUtils.locateOnScreenCenter(frame);
            frame.setVisible(true);
            cbDriverNo.setSelectedItem(new Driver(frame.getReturnStatus()));
        }
        catch (SQLException ex)
        {
            OutputError.toLog(ex);
            OutputError.toUser(ex);
        }
    }//GEN-LAST:event_btnMatchActionPerformed

    private void btnCancelActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnCancelActionPerformed
    {//GEN-HEADEREND:event_btnCancelActionPerformed
        if (AppUtils.askExitConfirm() == JOptionPane.YES_OPTION)
        {
            this.dispose();
        }
    }//GEN-LAST:event_btnCancelActionPerformed

    private void btnOkActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnOkActionPerformed
    {//GEN-HEADEREND:event_btnOkActionPerformed
        presentationModel.triggerCommit();
        DeliveryValidator validator = new DeliveryValidator(dateChooser, ckbDelivered.isSelected(), cbDriverNo.getSelectedItem());
        ValidationResult validationResult = validator.validate(new ValidationResult());
        ValidationUtil.displayErrorsToLable(validationResult, lblValidationErrors);

        if (validationResult.isEmpty())
        {
            Date deliveryDate = dateChooser.getDate();
            Character isDelivered = ckbDelivered.isSelected() ? '1' : '0';
            String deliveryNo = lblDeliveryNo.getText();
            Driver driverNo = (Driver) cbDriverNo.getSelectedItem();
            Delivery delivery = AppFactory.createDelivery(deliveryDate, isDelivered, deliveryNo, driverNo);

            int askUserQuestion = AppUtils.askUserQuestion(this, "Add/Edit the following?\n" + delivery, "Add/Edit", JOptionPane.YES_NO_CANCEL_OPTION);

            if (askUserQuestion == JOptionPane.YES_OPTION)
            {
                try
                {
                    if (delivery.getDeliveryNo() == null)
                    {
                        deliveryCrudService.create(delivery);
                        AppUtils.showUserMessage(this, "Added the following:\n" + delivery, "Add/Edit", JOptionPane.INFORMATION_MESSAGE);
                    }
                    else
                    {
                        AppFactory.createUpdatedDelivery(delivery, deliveryFromDb);
                        deliveryCrudService.edit(deliveryFromDb);
                        AppUtils.showUserMessage(this, "Updated the following:\n" + delivery, "Add/Edit", JOptionPane.INFORMATION_MESSAGE);
                    }
                    this.dispose();
                }
                catch (PreexistingEntityException ex)
                {
                    OutputError.toLog(ex);
                    OutputError.toUser(ex);
                }
                catch (Exception ex)
                {
                    OutputError.toLog(ex);
                    OutputError.toUser(ex);
                }
            }
        }
    }//GEN-LAST:event_btnOkActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCancel;
    private javax.swing.JButton btnMatch;
    private javax.swing.JButton btnOk;
    private javax.swing.JComboBox cbDriverNo;
    private javax.swing.JCheckBox ckbDelivered;
    private java.util.List<com.deliveryservicesystem.model.Driver> driverList;
    private javax.persistence.Query driverQuery;
    private javax.persistence.EntityManager entityManager;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JLabel lblDelivered;
    private javax.swing.JLabel lblDeliveryDate;
    private javax.swing.JLabel lblDeliveryNo;
    private javax.swing.JLabel lblDriverNo;
    private javax.swing.JLabel lblInfo;
    private javax.swing.JLabel lblValidationErrors;
    private javax.swing.JTextField txtDate;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables
}
